package com.soa.ocod;

import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Calendar;
import java.util.Date;
import java.util.StringTokenizer;
import java.util.logging.Logger;

import javax.net.ssl.HttpsURLConnection;

/**
 * 
 * OdSession
 * 
 * This class is used to maintain a session with On Demand for performing web
 * services call.
 * 
 * @author frederic_agneray
 * 
 */
public class OdSession {

  //public static String[] sessionids = new String[4];
  //public static Date[] timeForSession = { new Date(), new Date(), new Date(), new Date() };
  public static String[] sessionids = new String[1];
  public static Date[] timeForSession = {new Date()};
  private static Logger log = Logger.getLogger(OdSession.class.getName());
  private static int sessNum = 0;
  public static String USERNAME = "username";
  public static String PASSWORD = "password";
  public static String OCOD_URL = "ocodUrl";
  static String username = null;
  static String password = null;
  static String ocodUrl = null;

  public static String getSessionId() {
    //sessNum = (sessNum == 3 ? 0 : sessNum + 1);
    sessNum = 0;
    if (sessionids[sessNum] == null || isOld(timeForSession[sessNum])) {
      sessionids[sessNum] = getFreshSessionId();
    }
    timeForSession[sessNum].setTime(System.currentTimeMillis());
    return sessionids[sessNum];
  }

  /**
   * Log into a session with CRM On Demand
   */
  public static String getFreshSessionId() {
    try {
      if (sessionids[sessNum] != null){
        URL wsURL = new URL(ocodUrl + ";jsessionid=" + sessionids[sessNum] + "?command=logoff");
        HttpsURLConnection wsConnection = (HttpsURLConnection) wsURL.openConnection();
        wsConnection.setUseCaches(false);
        wsConnection.setRequestMethod("GET");
        wsConnection.connect();
      }
      URL wsURL = new URL(ocodUrl + "?command=login");
      HttpsURLConnection wsConnection = (HttpsURLConnection) wsURL.openConnection();
      wsConnection.setRequestProperty("UserName", username);
      wsConnection.setRequestProperty("Password", password);
      wsConnection.setUseCaches(false);
      wsConnection.setRequestMethod("GET");
      // see if we got a successful response
      int res = wsConnection.getResponseCode();
      if (res == HttpURLConnection.HTTP_OK) {
        // get the session id from the cookie setting
        String cookie = getCookieFromHeaders(wsConnection);
        return isolateSessionId(cookie);
      } else {
        log.severe("cannot login with given credentials");
        return null;
      }
    } catch (Exception e) {
      log.severe("Logon Exception generated :: " + e);
      return null;
    }
  }

  public static void reset() throws Exception {
    //sessionids = new String[4];
    sessionids = new String[1];
    OcodDbPropertyReader.reloadProperties();
    username = OcodDbPropertyReader.getProperty(USERNAME);
    password = PassEncryption.decrypt(OcodDbPropertyReader.getProperty(PASSWORD));
    ocodUrl = OcodDbPropertyReader.getProperty(OCOD_URL);
  }

  // return the header value (FAIL string for not found)
  private static String getCookieFromHeaders(HttpURLConnection wsConnection) {
    String headerName;
    String headerValue = "FAIL";
    for (int i = 0;; i++) {
      headerName = wsConnection.getHeaderFieldKey(i);
      if (headerName != null && headerName.equals("Set-Cookie")) {
        // found the Set-Cookie header (code assumes only one cookie is being
        // set)
        headerValue = wsConnection.getHeaderField(i);
        break;
      }
    }
    return headerValue;
  }

  private static String isolateSessionId(String cookie) {
    StringTokenizer st = new StringTokenizer(cookie, ";");
    String jsessionid = st.nextToken();
    st = new StringTokenizer(jsessionid, "=");
    st.nextToken();
    return st.nextToken();
  }

  public static boolean isOld(Date date) {
    Calendar cal = Calendar.getInstance();
    cal.add(Calendar.MINUTE, -10);
    Date nowMinusTen = cal.getTime();
    return date.compareTo(nowMinusTen) < 0;
  }

  public static void main(String[] args) {
    System.out.println(OdSession.getSessionId());
  }

}